package com.yiba.vpn.service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.transaction.Transactional;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.yiba.vpn.authorization.manager.TokenManager;
import com.yiba.vpn.config.ResultStatus;
import com.yiba.vpn.domain.RouterUser;
import com.yiba.vpn.dto.RouterDto;
import com.yiba.vpn.dto.SuperPojo;
import com.yiba.vpn.model.ResultModel;
import com.yiba.vpn.repository.RouterUserRepository;
import com.yiba.vpn.util.DateUtil;
import com.yiba.vpn.util.RandomUtil;
import com.yiba.vpn.util.RegexUtil;
import com.yiba.vpn.util.SMSSendUtil;

/**
 * @author : tang
 * @createtime ：2018年2月28日 上午11:34:11
 */
@Service
public class RouterSerivce {

	private static Logger logger = Logger.getLogger(RouterSerivce.class);

	private static Integer subscribeNum;

	private static SuperPojo sp = new SuperPojo();

	private static final Long NOTE_EFFECT_TIME = 600L;

	@Autowired
	private RouterUserRepository routerUserRepository;

	@Autowired
	private TokenManager tokenManager;

	@PostConstruct
	public void initSubscribeNum() {
		RouterUser routerUser = routerUserRepository.queryLastOne();
		subscribeNum = routerUser.getNum();
	}

	public ResponseEntity<ResultModel> getSubscribeNum() {
		sp.put("num", subscribeNum);
		return new ResponseEntity<ResultModel>(ResultModel.ok(sp), HttpStatus.OK);
	}

	public ResponseEntity<ResultModel> getCode(RouterDto routerDto) {

		SMSSendUtil uu = new SMSSendUtil();
		String telephoneNum = routerDto.getTelephoneNum();
		String vcode = RandomUtil.createVerifyCode();
		int sendMsg = uu.sendMsg(telephoneNum, "236212", new String[] { vcode, "10" });
		if (sendMsg == -2) {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.NOT_PHONE), HttpStatus.OK);
		} else if (sendMsg == 0) {
			// 发送成功，存储到redis中
			tokenManager.addV(telephoneNum, vcode, NOTE_EFFECT_TIME, TimeUnit.SECONDS);
			return new ResponseEntity<ResultModel>(ResultModel.ok(), HttpStatus.OK);
		} else {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.SEND_NOTE_FAIL), HttpStatus.OK);
		}
	}

	public ResponseEntity<ResultModel> subscribe(RouterDto routerDto) {
		String telephoneNum = routerDto.getTelephoneNum();
		String vcode = routerDto.getVcode();
		if (telephoneNum == null || vcode == null) {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.REQUEST_PARAMS_ERROR), HttpStatus.OK);
		}

		if (vcode.equals(tokenManager.getValue(telephoneNum))) {
			tokenManager.deleteKey(telephoneNum);
			// 验证码正确后，调用预约号num逻辑
			if (subscribeNum >= 100000) {
				return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.ROUTER_NUM_FULL), HttpStatus.OK);
			} else {
				executeSubscribe(routerDto);
				return new ResponseEntity<ResultModel>(ResultModel.ok(), HttpStatus.OK);
			}
		}
		return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.CODE_ERROR), HttpStatus.OK);
	}

	public ResponseEntity<ResultModel> getUserInfo(RouterDto routerDto) {

		String telephoneNum = routerDto.getTelephoneNum();
		if (telephoneNum == null) {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.REQUEST_PARAMS_ERROR), HttpStatus.OK);
		}
		try {
			RouterUser routerUser = routerUserRepository.findByPhone(telephoneNum);
			if (routerUser == null) {
				return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.USER_NOT_FOUND), HttpStatus.OK);
			}
			return new ResponseEntity<ResultModel>(ResultModel.ok(routerUser), HttpStatus.OK);
		} catch (Exception e) {
			logger.error("路由器预约获取当前用户信息异常 : " + e);
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.INTERNAL_SERVER_ERROR),
					HttpStatus.OK);
		}
	}

	public ResponseEntity<ResultModel> saveWallet(RouterDto routerDto) {
		String ethWallet = routerDto.getEthWallet();
		if (!RegexUtil.isWallet(ethWallet)) {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.NOT_WALLET), HttpStatus.OK);
		}

		RouterUser routerUser = new RouterUser();
		String telephoneNum = routerDto.getTelephoneNum();
		if (telephoneNum == null) {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.REQUEST_PARAMS_ERROR), HttpStatus.OK);
		}
		try {
			routerUser = routerUserRepository.findByPhone(telephoneNum);
		} catch (Exception e) {
			logger.error("路由器活动保存钱包时查询当前用户的钱包信息异常" + e);
		}

		if (routerUser == null) {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.USER_NOT_FOUND), HttpStatus.OK);
		}
		if (routerUser.getEthWallet() != null) {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.WALLET_HAD_EXIST), HttpStatus.OK);
		}

		routerUser.setEthWallet(ethWallet);
		routerUser.setWfee(50);
		try {
			routerUser = routerUserRepository.save(routerUser);
		} catch (Exception e) {
			logger.error("路由器活动保存钱包异常" + e);
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.WALLET_HAD_EXIST), HttpStatus.OK);
		}
		return new ResponseEntity<ResultModel>(ResultModel.ok(), HttpStatus.OK);
	}

	@Transactional
	private void executeSubscribe(RouterDto routerDto) {

		// 查询当前手机用户是否已存在
		RouterUser routerUserDB = routerUserRepository.findByPhone(routerDto.getTelephoneNum());
		if (routerUserDB == null) {
			Integer routerInt = RandomUtil.randomRouterInt();
			subscribeNum = subscribeNum + routerInt > 100000 ? 100000 : subscribeNum + routerInt;
			RouterUser routerUser = new RouterUser();
			routerUser.setPhone(routerDto.getTelephoneNum());
			routerUser.setNum(subscribeNum);
			try {
				routerUserRepository.save(routerUser);
			} catch (Exception e) {
				logger.error("路由器预约时存储手机号异常 : " + e);
			}
		}
	}

	public ResponseEntity<ResultModel> robot(Integer count) {
		if (count == null) {
			return new ResponseEntity<ResultModel>(ResultModel.error(ResultStatus.REQUEST_PARAMS_ERROR), HttpStatus.OK);
		}
		for (int i = 0; i < count; i++) {
			RouterDto routerDto = new RouterDto();
			routerDto.setTelephoneNum(DateUtil.getTimestamp(new Date()) + "");
			executeSubscribe(routerDto);
		}
		sp.put("num", subscribeNum);
		return new ResponseEntity<ResultModel>(ResultModel.ok(sp), HttpStatus.OK);
	}

}
